fix: autodetecta binário do LibreOffice na conversão de DOCX para PDF - #1292
Conversation
convert_docx_to_pdf tinha default="libreoffice", mas o CLI (pdf_generator.py) sempre repassava arguments.libreoffice_binary explicitamente, que fica None quando --libreoffice-binary não é informado - isso sobrescrevia o default da função (default de parâmetro só vale quando o argumento não é passado na chamada) e quebrava o subprocess com TypeError, mesmo com o LibreOffice instalado e no PATH. Move a resolução do binário para dentro de convert_docx_to_pdf: autodetecta via shutil.which (tenta "libreoffice", depois "soffice", já que várias instalações só têm um dos dois) e levanta RuntimeError claro quando nada é encontrado, em vez do TypeError interno do subprocess. Fixes scieloorg#1291.
| if not libreoffice_binary: | ||
| libreoffice_binary = shutil.which("libreoffice") or shutil.which("soffice") | ||
| if not libreoffice_binary: | ||
| raise RuntimeError( | ||
| "LibreOffice binary not found on PATH. Install LibreOffice, or pass " | ||
| "libreoffice_binary (CLI: --libreoffice-binary) with the path to the " | ||
| "'libreoffice' or 'soffice' executable." | ||
| ) |
There was a problem hiding this comment.
Sugiro chamar de binary pois pode ser MSOffice, LibreOffice, etc. Sugiro também que trate como FileNotFoundError.
binary = libreoffice_binary or shutil.which("libreoffice") or shutil.which("soffice")
if not binary:
raise FileNotFoundError("LibreOffice binary ('libreoffice' or 'soffice') was not found")There was a problem hiding this comment.
Concordo, ajustado. Renomeei a variável resolvida para binary e troquei RuntimeError por FileNotFoundError quando o binário não é encontrado, seguindo o snippet sugerido. Commit a1d31d51.
| output_dir = os.path.dirname(docx_path) | ||
| os.makedirs(output_dir, exist_ok=True) |
There was a problem hiding this comment.
Se informar na CLI "-o saida.pdf", aqui vai gerar um os.makedirs(""), causando erro. Sugiro corrigir para algo como:
output_dir = os.path.dirname(docx_path) or "."
if output_dir != ".":
os.makedirs(output_dir, exist_ok=True)Veja o que ocorre com "saida.pdf":
>>> os.path.dirname("saida.pdf")
''
>>> os.makedirs('')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<frozen os>", line 225, in makedirs
FileNotFoundError: [Errno 2] No such file or directory: ''
>>> E com ".":
>>> os.makedirs('.', exist_ok=True)
>>> There was a problem hiding this comment.
Bom achado, é o mesmo bug da issue #773. Corrigido com output_dir = os.path.dirname(docx_path) or ".", pulando o makedirs nesse caso. Validei manualmente com -o saida.pdf (sem diretório): gera o PDF normalmente agora. Coberto também em test_docx_path_without_directory_component_does_not_raise. Commit a1d31d51.
pitangainnovare
left a comment
There was a problem hiding this comment.
Precisa fazer pequenos ajustes que envolvem o makedirs
Ajustes pedidos na revisão do PR scieloorg#1292: - Variável do binário resolvido renomeada para "binary" (pode ser libreoffice ou soffice, não só "libreoffice"); ausência agora levanta FileNotFoundError em vez de RuntimeError. - output_dir = os.path.dirname(docx_path) é "" quando docx_path não tem componente de diretório (ex.: CLI com -o saida.pdf), e os.makedirs("") levanta FileNotFoundError - mesmo bug já registrado na issue scieloorg#773. Corrigido com output_dir = os.path.dirname(docx_path) or "." e pulando o makedirs nesse caso. Validado manualmente com "-o saida.pdf" (sem diretório) - antes quebrava, agora gera o PDF normalmente.
O que esse PR faz?
Corrige o comando
pdf_generator(CLI de geração de PDF), que quebrava ao converter o DOCX intermediário para PDF quando a flag--libreoffice-binarynão era informada, mesmo com o LibreOffice instalado noPATH.convert_docx_to_pdfagora autodetecta o binário (tentalibreoffice, depoissoffice) viashutil.which, e levanta umRuntimeErrorclaro quando nenhum é encontrado, em vez doTypeErrorinterno desubprocessque ocorria antes.Onde a revisão poderia começar?
packtools/sps/formats/pdf/utils/file_utils.py, funçãoconvert_docx_to_pdf.Como este poderia ser testado manualmente?
Com o LibreOffice instalado (
sofficeoulibreofficenoPATH):Antes deste PR, esse comando quebrava com
TypeError: expected str, bytes or os.PathLike object, not NoneType. Depois, gerasaida.pdfnormalmente.Testes automatizados:
python -m unittest tests.sps.formats.pdf.utils.test_file_utils -v(4 casos: binário explícito respeitado, autodetecção delibreoffice, fallback parasoffice, erro claro sem binário).Algum cenário de contexto que queira dar?
--libreoffice-binarynão tinhadefaultnoargparsedo CLI, então ficavaNonequando omitida — e esseNoneera repassado explicitamente paraconvert_docx_to_pdf, sobrescrevendo o default"libreoffice"que a própria função já declarava (um default de parâmetro só é usado quando o argumento não é passado na chamada; o CLI sempre passava). Isso bloqueava a geração de PDF para qualquer usuário seguindo o--helpdo comando.Screenshots
N/A (mudança de backend/CLI, sem interface visual).
Quais são os tickets relevantes?
Closes #1291.
Referências
N/A
Segurança da informação (NSI.04)
Este PR manipula dados sensíveis ou pessoais (LGPD)?
Este PR altera autenticação, autorização, controle de acesso ou gerenciamento de sessão?
Este PR introduz, atualiza ou remove dependências de terceiros?
Este PR foi validado pelo pipeline de segurança (SonarQube / Trivy)?
SECURITY_ADHERENCE.md. Os gates automáticos reais deste repositório (Snyk e GitGuardian) rodam via CI neste PR.Este PR concatena, monta ou executa comandos SQL, HTML ou JavaScript a partir de entrada externa?
subprocess.runcom lista de argumentos fixa (semshell=True, sem interpolação de entrada externa).Este PR expõe novos endpoints, telas ou serviços?
Algum segredo, senha, chave ou token está sendo adicionado ao código-fonte?